//
// Created by Asus on 2025/5/13.
//
/**
 * demo Lambda 函数的多种使用示例，覆盖常见场景和闭包行为
* 关键总结
语法结构：[捕获列表](参数列表)->返回类型{函数体}
捕获方式：
[]：不捕获任何变量
[x, &y]：值捕获x，引用捕获y
[=]：隐式值捕获所有变量
[&]：隐式引用捕获所有变量
[=, &z]：默认值捕获，显式引用捕获z
注意事项：
值捕获创建副本，不影响原始变量
引用捕获可能导致悬空引用（如捕获局部变量后函数返回）
使用mutable允许修改值捕获的副本
捕获this指针时需确保对象生命周期长于 Lambda

Lambda 函数是 C++ 中强大的语法糖，常用于简化回调函数、临时操作和算法实现，能显著提升代码的可读性和简洁性。
 */

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
#include <bits/ostream.tcc>
// 1. 基础语法：无捕获、带参数、显式返回类型
void demo01() {
    auto sum = [](int a, int b) { return a + b; };
    std::cout << "sum is: " << sum(1, 2) << std::endl;
    std::cout << "sum is: " << [](int a, int b) { return a + b; }(1, 2) << std::endl;
}

// 2. 闭包捕获：值捕获与引用捕获
void demo02() {
    int x = 10, y = 20;

    // 值捕获：复制外部变量
    auto addX = [x](int num) { return num + x; };
    std::cout << "Add X: " << addX(5) << std::endl; // 输出：15（x=10）

    // 引用捕获：直接使用外部变量的引用
    auto modifyY = [&y](int delta) { y += delta; };
    modifyY(5);
    std::cout << "Modified Y: " << y << std::endl; // 输出：25

    // 混合捕获：值捕获x，引用捕获y
    auto complex = [x, &y]() { return x + (y *= 2); };
    std::cout << "Complex: " << complex() << std::endl; // 输出：10 + 50 = 60（y变为50）
}

// 3. 隐式捕获：[=] 和 [&]
void demo03() {
    int a = 1, b = 2, c = 3;

    // [=]：隐式值捕获所有外部变量
    auto sumAll = [=]() { return a + b + c; };
    std::cout << "Sum All: " << sumAll() << std::endl; // 输出：6

    // [&]：隐式引用捕获所有外部变量
    auto multiplyAll = [&](int factor) {
        a *= factor;
        b *= factor;
        c *= factor;
    };
    multiplyAll(2);
    std::cout << "New a: " << a << ", b: " << b << ", c: " << c << std::endl; // 输出：2, 4, 6

    // 混合模式：[&, a] 除a外引用捕获
    auto updateBC = [&, a](int value) {
        b = a + value;
        c = a - value;
    };
    updateBC(5);
    std::cout << "Updated b: " << b << ", c: " << c << std::endl; // 输出：7, -3
}

// 4. 在标准库算法中使用 Lambda
void demo04() {
    std::vector<int> nums = {3, 1, 4, 1, 5, 9};

    // 使用lambda排序（降序）
    std::sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; });
    for (int num: nums) std::cout << num << " "; // 输出：9 5 4 3 1 1

    // 使用lambda过滤元素
    auto evenCount = std::count_if(nums.begin(), nums.end(), [](int num) { return num % 2 == 0; });
    std::cout << "\n偶数个数: " << evenCount << std::endl; // 输出：2

    // 使用lambda修改元素
    std::for_each(nums.begin(), nums.end(), [](int &num) { num *= 2; });
    for (int num: nums) std::cout << num << " "; // 输出：18 10 8 6 2 2
}

// 5. 捕获this指针（类成员函数中）

class Calculator {
private:
    int value = 0;

public:
    void add(int x) {
        // 捕获this指针，访问类成员
        auto lambda = [this](int num) { this->value += num; };
        lambda(x);
    }

    int getValue() const { return value; }
};

void demo05() {
    Calculator calc;
    calc.add(5);
    std::cout << "Value: " << calc.getValue() << std::endl; // 输出：5
}

// 6. 可变 Lambda（修改值捕获的变量）
void demo06() {
    int x = 10;

    // 普通值捕获无法修改x
    // auto bad = [x]() { x++; };  // 错误：无法修改值捕获的变量

    // 使用mutable允许修改值捕获的副本
    auto good = [x]() mutable {
        x++;
        std::cout << "内部x: " << x << std::endl;
    };
    good(); // 输出：11
    std::cout << "外部x: " << x << std::endl; // 输出：10（原始x未被修改）
}

// 7. 泛型 Lambda（C++14+）
void demo07() {
    // 使用auto参数创建泛型lambda
    auto print = [](const auto &value) {
        std::cout << "值: " << value << std::endl;
    };

    print(42); // 输出：值: 42
    print("hello"); // 输出：值: hello
    print(3.14); // 输出：值: 3.14
}


// 8. 延迟执行（保存 Lambda 供后续调用）
std::function<void()> createPrinter() {
    int x = 100;
    // 捕获x的值，即使函数返回后仍保留
    return [x]() { std::cout << "延迟打印: " << x << std::endl; };
}

void demo08() {
    auto printer = createPrinter();
    printer(); // 输出：延迟打印: 100
}

int main(char *argv[]) {
    // 1. 基础语法：无捕获、带参数、显式返回类型
    demo01();
}
